package com.houor.device.controller.handler.codec;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.houor.device.DeviceConstants;
import com.houor.device.controller.data.ControllerFrame;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

/**
 * 输入帧解码
 * 
 * @author Houor
 *
 * @createTime 2017-04-20 22:54
 */
public class ControllerFrameDecoder extends ByteToMessageDecoder {

	private static Logger logger = LoggerFactory.getLogger(ControllerFrameDecoder.class);

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
		logger.debug("byte buffer length: {}, content: {}.", in.readableBytes(), ByteBufUtil.hexDump(in));
		int dataLength = in.readableBytes();
		// byte[] data = new byte[dataLength];
		// in.readBytes(data);

		// check start and end byte
		if (in.getByte(0) != DeviceConstants.CONTROLLER_START_FLAG) {
			logger.debug("start byte error.");
			in.clear();
			return;
		}

		if (in.getByte(dataLength - 1) != DeviceConstants.CONTROLLER_END_FLAG) {
			logger.debug("end byte error.");
			in.clear();
			return;
		}

		// check data content length(data length byte: 1-2)
		// short contentLength = in.getShort(1);
		if (dataLength != (in.getShort(1) + 3)) {
			logger.debug("data content length error.");
			in.clear();
			return;
		}

		// check checksum
		byte checksum = 0x00;
		int count = dataLength - 2;
		for (int i = 1; i < count; i++) {
			checksum = (byte) (checksum + in.getByte(i));
		}
		if (in.getByte(dataLength - 2) != checksum) {
			logger.debug("data content checksum error.");
//			in.clear();
//			return;
		}

		ControllerFrame frame = new ControllerFrame();
		frame.setStart(in.readByte());
		frame.setLength(in.readShort());
		frame.setDeviceID(in.readLong());
		frame.setDeviceType(in.readByte());
		frame.setCommand(in.readByte());
		frame.setStatus(in.readByte());
		byte[] content = new byte[frame.getLength() - 13];
		in.readBytes(content);
		frame.setContent(content);
		frame.setChecksum(in.readByte());
		frame.setEnd(in.readByte());

		// frame.init(data);

		out.add(frame);

	}

}
